# -*- coding: utf-8 -*-
# created on 2016/10/31
from mathsolver.functions.hanshu.base import expr_split, is_equal
from sympy import sqrt, Mul, simplify, Pow
from sympy.abc import x, t
from sympy.core.numbers import Integer
from mathsolver.functions.base.base import BaseFunction, new_latex
from mathsolver.functions.base.objects import BaseFunc, BaseEq, BaseFuncName
from mathsolver.functions.root.jiefangchen import JieFangChen
from mathsolver.functions.sympy_utils import default_symbol


class HuanYuanFaQiuHanShuJieXiShi(BaseFunction):
    def solver(self, *args):
        """
        用换元法求函数解析式
        :param args: [0] - BaseFunc 形如f(g(x))=h(x)的解析式, [1] - i(x) 默认为x
        :return: BaseFunc 形如f(i(x))的解析式
        """
        self.label.add("换元法求函数解析式")
        expr = args[0].expression
        sym = args[0].var
        default_sym = default_symbol(sym)
        ix = x
        if len(args) == 2:
            ix = args[1].var
        if sym.is_Atom:
            return self
        tihuan = JieFangChen(verbose=True).solver(BaseEq([sym, 't'])).output[0].value[default_symbol(sym)].args[
            0].factor()
        self.steps.append(["令{}=t".format(new_latex(sym)), "则{}={}".format(new_latex(default_sym), new_latex(tihuan))])
        if isinstance(tihuan, Pow) and tihuan.args[1] == 2:
            if expr.has(sqrt(default_sym)):
                expr = expr.subs(sqrt(default_sym), tihuan.args[0])
        expr_subs = simplify(expr.subs(default_sym, tihuan))
        self.steps.append(["代入原解析式", "得f(t)={}".format(new_latex(expr_subs))])
        if ix == x:
            expr_subs = expr_subs.subs(t, x)
            self.steps.append(["∴ f({})={}".format(new_latex(default_sym), new_latex(expr_subs)), ""])
            self.output.append(
                BaseFunc({'name': 'f', 'var': default_sym, 'type': '', 'expression': expr_subs}))
        else:
            expr_subs = simplify(expr_subs.subs(t, ix))
            self.steps.append(["∴ f({})={}".format(new_latex(ix), new_latex(expr_subs)), ""])
            self.output.append(
                BaseFuncName({'name': 'f', 'var': ix, 'type': '', 'expression': expr_subs}))
        return self


class CouPeiFaQiuHanShuJieXiShi(BaseFunction):
    def solver(self, *args):
        """
        用凑配法求函数解析式，只能解f(g(x)+1/g(x))=h(x)或f((g(x)-1/gx))=h(x)的形式
        :param args: [0] - BaseFunc 解析式, [1] - i(x) 默认为x
        :return: BaseFunc 形如f(i(x))的解析式
        """
        self.label.add("凑配法求函数解析式")
        expr = args[0].expression
        sym = args[0].var
        default_sym = default_symbol(sym)
        ix = x
        if len(args) == 2:
            ix = args[1].var
        if sym.is_Atom:
            return self
        lx, op, lx_b = expr_split(sym)
        if lx.is_Symbol:
            if lx_b.args[1] != -1:
                return self
        else:
            if lx_b.args[1] + lx.args[1] != 0:
                return self
        right = expr_split(expr)
        a, b, c = 1, 0, 0
        for index in range(len(right)):
            if isinstance(right[index], str):
                continue
            elif isinstance(right[index], Integer) or right[index].is_Number:
                c = right[index]
            elif is_equal(right[index], lx ** 2):
                if index > 1:
                    if isinstance(right[index - 1], str):
                        a = -1 if right[index - 1] == '-' else 1
                    else:
                        a = 1
            elif is_equal(right[index], lx):
                if index > 1:
                    if isinstance(right[index - 1], str):
                        b = -1 if right[index - 1] == '-' else 1
            elif isinstance(right[index], Mul):
                if is_equal(right[index].args[1], lx ** 2):
                    if index > 1:
                        if isinstance(right[index - 1], str):
                            a = right[index].args[0]
                            a = -a if right[index - 1] == '-' else a
                elif is_equal(right[index].args[1], lx):
                    if index > 1:
                        if isinstance(right[index - 1], str):
                            b = right[index].args[0]
                            b = -b if right[index - 1] == '-' else b
        del right
        if op == '+':
            tail = c - 2 * a
            expr_final = simplify(a * ix ** 2 + b * ix + c - 2 * a)
        elif op == '-':
            tail = c + 2 * a
            expr_final = simplify(a * ix ** 2 + b * ix + c + 2 * a)
        self.steps.append(["{}({})={}".format(args[0].name, new_latex(args[0].var), new_latex(expr)), ""])
        stepstr = "={}({}+{})".format(a if a != 1 else "", new_latex(lx ** 2), new_latex(lx_b ** 2))
        if b < 0:
            stepstr += "-{}({})".format(-b if b != -1 else "", new_latex(sym))
        elif b > 0:
            stepstr += "+{}({})".format(b if b != 1 else "", new_latex(sym))
        if c < 0:
            stepstr += "-" + str(-c)
        elif c > 0:
            stepstr += "+" + str(c)
        self.steps.append([stepstr, ""])
        stepstr = "={}{}".format(a if a != 1 else "", new_latex(sym ** 2))
        if b < 0:
            stepstr += "-{}({})".format(-b if b != -1 else "", new_latex(sym))
        elif b > 0:
            stepstr += "+{}({})".format(b if b != 1 else "", new_latex(sym))
        if tail < 0:
            stepstr += "-" + str(-tail)
        elif tail > 0:
            stepstr += "+" + str(tail)
        self.steps.append([stepstr, ""])
        if ix == x:
            self.steps.append(["∴ {}({})={}".format(args[0].name, default_sym, new_latex(expr_final)), ""])
            self.output.append(BaseFunc({'name': 'f', 'var': default_sym, 'type': '', 'expression': expr_final}))
        else:
            self.steps.append(["∴ {}({})={}".format(args[0].name, new_latex(ix), new_latex(expr_final)), ""])
            self.output.append(BaseFuncName({'name': 'f', 'var': ix, 'type': '', 'expression': expr_final}))
        return self


if __name__ == '__main__':
    pass
